<script lang="ts" setup>
const props = withDefaults(defineProps<{
  json: Record<string, any>,
  title?: string,
  highLight?: boolean,
  theme?: 'light' | 'dark'
}>(), {
  title: '',
  highLight: true,
  theme: 'dark'
})

onMounted(() => {
  openWindow()
})

// region TODO 打开和关闭窗体
let isClose = false
let win: Window = null
function openWindow () {
  const strWindowFeatures = 'width=400,height=450,screenX=400,screenY=200'
  const target = Date.now() + Math.random() + ''
  win = window.open('', target, strWindowFeatures)
  if (!win) {
    setTimeout(() => { !isClose && openWindow() }, 500)
  } else {
    win.document.write(`<html lang="cn"><head><title>${props.title}</title></head></html>`)
    win.document.body.style.fontSize = '16px'
    win.document.body.style.lineHeight = '1.5'
    win.document.body.style.backgroundColor = colors.bg
    win.document.body.style.color = colors.text
    window.addEventListener('beforeunload', closeWindow)
    render()
  }
}

function closeWindow () {
  isClose = true
  win && win.close()
}
// endregion

// region TODO 渲染数据
watch(() => props.json, () => {
  render()
}, { deep: true })

function render () {
  const json = isRef(props.json) ? props.json.value : props.json
  const jsonStr = props.highLight ? syntaxHighlight(json) : JSON.stringify(json)
  win.document.body.innerHTML = `<pre><code>${jsonStr}</code></pre>`
}
const colorTheme = {
  light: {
    text: '#000000',
    bg: '#FFFFFF',
    default: '#1e6096',
    attr: '#ab1515',
    string: '#4a9c6b',
    boolean: '#7092e8',
    null: '#acacac'
  },
  dark: {
    text: '#FFFFFF',
    bg: '#1e1f22',
    default: '#3e9adb',
    attr: '#c77dbb',
    string: '#4a9c69',
    boolean: '#ce7140',
    null: '#acacac'
  }
}
const colors = colorTheme[props.theme]
function syntaxHighlight (json:any) {
  if (typeof json !== 'string') {
    json = JSON.stringify(json, undefined, 2)
  }
  json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
  return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\\-]?\d+)?)/g, function (match) {
    let cls = colors.default
    if (/^"/.test(match)) {
      if (/:$/.test(match)) {
        cls = colors.attr
      } else {
        cls = colors.string
      }
    } else if (/true|false/.test(match)) {
      cls = colors.boolean
    } else if (/null/.test(match)) {
      cls = colors.null
    }
    return `<span style="color:${cls}">${match}</span>`
  })
}
// endregion

onBeforeUnmount(() => {
  closeWindow()
})

</script>
